﻿using NPlot;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using NPlot.Windows;
using Server.MessageModule.Message;

namespace Server.ChartLog
{
    public partial class ChartDisplay : Form
    {
        private LinePlot _lineAcelX;
        private LinePlot _lineAcelY;
        private LinePlot _lineAcelZ;

        private LinePlot _lineAcelXKalman;
        private LinePlot _lineAcelYKalman;
        private LinePlot _lineAcelZKalman;

        private LinePlot _lineMagOrgX;
        private LinePlot _lineMagOrgY;
        private LinePlot _lineMagOrgZ;

        private List<float[]> _accelData;
        private List<float[]> _magOrData;

        //private long _offset = 0;
        private int _chartLength = 400;
        private int _mps = 40;

        public ChartDisplay()
        {
            _accelData = new List<float[]>();
            _magOrData = new List<float[]>();

            InitializeComponent();
        }

        private void ChartDisplay_Load(object sender, EventArgs e)
        {
            initChart();
            System.Timers.Timer timer = new System.Timers.Timer(25);
            timer.Elapsed += timer_Elapsed;
            timer.Enabled = true;
            timer.Start();

            
        }

        void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            updateChart();
        }

        private void updateChart()
        {
            List<float[]> data = new List<float[]>(_accelData);
            //System.Console.WriteLine("Num ACCDATA: " + _accelData.Count);
            int lenght = _chartLength;
            int offset = data.Count - lenght;
            if (offset < 0)
            {
                offset = 0;
                lenght = data.Count;
            }

            float[] accTime = new float[lenght];
            float[] accDataX = new float[lenght];
            float[] accDataY = new float[lenght];
            float[] accDataZ = new float[lenght];
            float[] accDataXK = new float[lenght];
            float[] accDataYK = new float[lenght];
            float[] accDataZK = new float[lenght];
            for (int i = 0; i < lenght; i++)
            {
                accTime[i] = (lenght - i) * 1.0f / _mps;
                accDataX[i] = data[offset + i][0];
                accDataY[i] = data[offset + i][1];
                accDataZ[i] = data[offset + i][2];
                accDataXK[i] = data[offset + i][3];
                accDataYK[i] = data[offset + i][4];
                accDataZK[i] = data[offset + i][5];
            }

            //float[] abc = new float[3];
            //abc[0] = 1;
            //abc[1] = 0.5f;
            //abc[2] = 4;

            //_lineAcelX.AbscissaData = accTime;
            if (_plotSurface2DX.InvokeRequired)
                _plotSurface2DX.BeginInvoke((MethodInvoker)delegate()
                {
                    _lineAcelX.AbscissaData = accTime;
                    _lineAcelY.AbscissaData = accTime;
                    _lineAcelZ.AbscissaData = accTime;
                    _lineAcelXKalman.AbscissaData = accTime;
                    _lineAcelYKalman.AbscissaData = accTime;
                    _lineAcelZKalman.AbscissaData = accTime;
                    _lineAcelX.DataSource = accDataX;
                    _lineAcelY.DataSource = accDataY;
                    _lineAcelZ.DataSource = accDataZ;
                    _lineAcelXKalman.DataSource = accDataXK;
                    _lineAcelYKalman.DataSource = accDataYK;
                    _lineAcelZKalman.DataSource = accDataZK;

                    _plotSurface2DX.Refresh();
                    _plotSurface2DY.Refresh();
                    _plotSurface2DZ.Refresh();
                });
        }

        private void initChart()
        {
            float max = 20;
            float min = -20;
            _plotSurface2DX.Clear();
            _plotSurface2DY.Clear();
            _plotSurface2DZ.Clear();

            NPlot.Grid p = new Grid();
            _plotSurface2DX.Add(p, NPlot.PlotSurface2D.XAxisPosition.Bottom,
                          NPlot.PlotSurface2D.YAxisPosition.Left);
            _plotSurface2DY.Add(p, NPlot.PlotSurface2D.XAxisPosition.Bottom,
                          NPlot.PlotSurface2D.YAxisPosition.Left);
            _plotSurface2DZ.Add(p, NPlot.PlotSurface2D.XAxisPosition.Bottom,
                          NPlot.PlotSurface2D.YAxisPosition.Left);

            _lineAcelX = new LinePlot();
            _lineAcelX.Label = "AccelerX";
            _lineAcelX.Color = System.Drawing.Color.Red;

            _lineAcelY = new LinePlot();
            _lineAcelY.Label = "AccelerY";
            _lineAcelY.Color = System.Drawing.Color.Green;

            _lineAcelZ = new LinePlot();
            _lineAcelZ.Label = "AccelerZ";
            _lineAcelZ.Color = System.Drawing.Color.Blue;

            _plotSurface2DX.Add(_lineAcelX, NPlot.PlotSurface2D.XAxisPosition.Bottom, NPlot.PlotSurface2D.YAxisPosition.Left);
            _plotSurface2DY.Add(_lineAcelY, NPlot.PlotSurface2D.XAxisPosition.Bottom, NPlot.PlotSurface2D.YAxisPosition.Left);
            _plotSurface2DZ.Add(_lineAcelZ, NPlot.PlotSurface2D.XAxisPosition.Bottom, NPlot.PlotSurface2D.YAxisPosition.Left);

            // Kalman line
            _lineAcelXKalman = new LinePlot();
            _lineAcelXKalman.Label = "Kalman AccelerX";
            _lineAcelXKalman.Color = System.Drawing.Color.Black;

            _lineAcelYKalman = new LinePlot();
            _lineAcelYKalman.Label = "Kalman AccelerY";
            _lineAcelYKalman.Color = System.Drawing.Color.Black;

            _lineAcelZKalman = new LinePlot();
            _lineAcelZKalman.Label = "Kalman AccelerZ";
            _lineAcelZKalman.Color = System.Drawing.Color.Black;

            _plotSurface2DX.Add(_lineAcelXKalman, NPlot.PlotSurface2D.XAxisPosition.Bottom, NPlot.PlotSurface2D.YAxisPosition.Left);
            _plotSurface2DY.Add(_lineAcelYKalman, NPlot.PlotSurface2D.XAxisPosition.Bottom, NPlot.PlotSurface2D.YAxisPosition.Left);
            _plotSurface2DZ.Add(_lineAcelZKalman, NPlot.PlotSurface2D.XAxisPosition.Bottom, NPlot.PlotSurface2D.YAxisPosition.Left);

            //
            _plotSurface2DX.Title = "Line Graph";
            _plotSurface2DX.BackColor = System.Drawing.Color.White;

            //Font definitions:
            Font TitleFont = new Font("Arial", 12);
            Font AxisFont = new Font("Arial", 10);
            Font TickFont = new Font("Arial", 8);
            //X axis
            //_plotSurface2DX.XAxis1.Label = "Time";
            _plotSurface2DX.XAxis1.NumberFormat = "{0:####0.0}";
            _plotSurface2DX.XAxis1.TicksLabelAngle = 90;
            _plotSurface2DX.XAxis1.TickTextNextToAxis = true;
            _plotSurface2DX.XAxis1.FlipTicksLabel = true;
            _plotSurface2DX.XAxis1.LabelOffset = 100;
            _plotSurface2DX.XAxis1.LabelOffsetAbsolute = true;
            _plotSurface2DX.XAxis1.LabelFont = AxisFont;
            _plotSurface2DX.XAxis1.TickTextFont = TickFont;
            _plotSurface2DX.XAxis1.WorldMax = 10;

            //Y axis
            _plotSurface2DX.YAxis1.Label = "Value";
            _plotSurface2DX.YAxis1.NumberFormat = "{0:####0.0}";
            _plotSurface2DX.YAxis1.LabelFont = AxisFont;
            _plotSurface2DX.YAxis1.TickTextFont = TickFont;
            _plotSurface2DX.YAxis1.WorldMax = max;
            _plotSurface2DX.YAxis1.WorldMin = min;

            //X axis
            //_plotSurface2DY.XAxis1.Label = "Time";
            _plotSurface2DY.XAxis1.NumberFormat = "{0:####0.0}";
            _plotSurface2DY.XAxis1.TicksLabelAngle = 90;
            _plotSurface2DY.XAxis1.TickTextNextToAxis = true;
            _plotSurface2DY.XAxis1.FlipTicksLabel = true;
            _plotSurface2DY.XAxis1.LabelOffset = 100;
            _plotSurface2DY.XAxis1.LabelOffsetAbsolute = true;
            _plotSurface2DY.XAxis1.LabelFont = AxisFont;
            _plotSurface2DY.XAxis1.TickTextFont = TickFont;
            _plotSurface2DY.XAxis1.WorldMax = 10;

            //Y axis
            _plotSurface2DY.YAxis1.Label = "Value";
            _plotSurface2DY.YAxis1.NumberFormat = "{0:####0.0}";
            _plotSurface2DY.YAxis1.LabelFont = AxisFont;
            _plotSurface2DY.YAxis1.TickTextFont = TickFont;
            _plotSurface2DY.YAxis1.WorldMax = max;
            _plotSurface2DY.YAxis1.WorldMin = min;

            //X axis
           // _plotSurface2DZ.XAxis1.Label = "Time";
            _plotSurface2DZ.XAxis1.NumberFormat = "{0:####0.0}";
            _plotSurface2DZ.XAxis1.TicksLabelAngle = 90;
            _plotSurface2DZ.XAxis1.TickTextNextToAxis = true;
            _plotSurface2DZ.XAxis1.FlipTicksLabel = true;
            _plotSurface2DZ.XAxis1.LabelOffset = 100;
            _plotSurface2DZ.XAxis1.LabelOffsetAbsolute = true;
            _plotSurface2DZ.XAxis1.LabelFont = AxisFont;
            _plotSurface2DZ.XAxis1.TickTextFont = TickFont;
            _plotSurface2DZ.XAxis1.WorldMax = 10;

            //Y axis
            _plotSurface2DZ.YAxis1.Label = "Value";
            _plotSurface2DZ.YAxis1.NumberFormat = "{0:####0.0}";
            _plotSurface2DZ.YAxis1.LabelFont = AxisFont;
            _plotSurface2DZ.YAxis1.TickTextFont = TickFont;
            _plotSurface2DZ.YAxis1.WorldMax = max;
            _plotSurface2DZ.YAxis1.WorldMin = min;

            //Add legend:
            Legend npLegend = new NPlot.Legend();
            npLegend.AttachTo(NPlot.PlotSurface2D.XAxisPosition.Top,
                     NPlot.PlotSurface2D.YAxisPosition.Right);
            npLegend.VerticalEdgePlacement = NPlot.Legend.Placement.Inside;
            npLegend.HorizontalEdgePlacement = NPlot.Legend.Placement.Outside;
            npLegend.BorderStyle = NPlot.LegendBase.BorderType.Line;
            _plotSurface2DX.Legend = npLegend;
            _plotSurface2DY.Legend = npLegend;
            _plotSurface2DZ.Legend = npLegend;

            //Update PlotSurface:
            _plotSurface2DX.Refresh();
            _plotSurface2DY.Refresh();
            _plotSurface2DZ.Refresh();
        }


        public void pushSensorData(SensorMessage message)
        {
            if (message == null)
                return;
            float[] acc = new float[6];
            acc[0] = message.Accel["x"];
            acc[1] = message.Accel["y"];
            acc[2] = message.Accel["z"];
            acc[3] = message.Accel["xk"];
            acc[4] = message.Accel["yk"];
            acc[5] = message.Accel["zk"];

            _accelData.Add(acc);
        }

        private void CreateLineGraph()
        {

            NPlot.LinePlot npPlot1 = new LinePlot();
            NPlot.LinePlot npPlot2 = new LinePlot();
            NPlot.LinePlot npPlot3 = new LinePlot();

            //Font definitions:
            Font TitleFont = new Font("Arial", 12);
            Font AxisFont = new Font("Arial", 10);
            Font TickFont = new Font("Arial", 8);

            //Legend definition:
            NPlot.Legend npLegend = new NPlot.Legend();

            DateTime[] X1 = new DateTime[50];
            DateTime[] X2 = new DateTime[50];
            int[] Y1 = new int[50];
            int[] Y2 = new int[50];

            Random r1 = new Random();
            Random r2 = new Random();

            for (int i = 0; i < 50; i++)
            {
                X1[i] = DateTime.Now.Date.AddDays(i);
                X2[i] = DateTime.Now.Date.AddDays(i);
                Y1[i] = r1.Next(100);
                Y2[i] = r2.Next(300);
            }

            //Prepare PlotSurface:
            _plotSurface2DX.Clear();
            _plotSurface2DX.Title = "Line Graph";
            _plotSurface2DX.BackColor = System.Drawing.Color.White;

            //Left Y axis grid:
            NPlot.Grid p = new Grid();
            _plotSurface2DX.Add(p, NPlot.PlotSurface2D.XAxisPosition.Bottom,
                          NPlot.PlotSurface2D.YAxisPosition.Left);

            //Weight:
            npPlot1.AbscissaData = X1;
            npPlot1.DataSource = Y1;
            npPlot1.Label = "Weight (kg.)";
            npPlot1.Color = System.Drawing.Color.Blue;

            //Height
            npPlot2.AbscissaData = X2;
            npPlot2.DataSource = Y2;
            npPlot2.Label = "Height (cm)";
            npPlot2.Color = System.Drawing.Color.Green;


            _plotSurface2DX.Add(npPlot1, NPlot.PlotSurface2D.XAxisPosition.Bottom,
                          NPlot.PlotSurface2D.YAxisPosition.Left);
            _plotSurface2DX.Add(npPlot2, NPlot.PlotSurface2D.XAxisPosition.Bottom,
                          NPlot.PlotSurface2D.YAxisPosition.Left);

            //X axis
            _plotSurface2DX.XAxis1.Label = "Date";
            _plotSurface2DX.XAxis1.NumberFormat = "yyyy-MM-dd";
            _plotSurface2DX.XAxis1.TicksLabelAngle = 90;
            _plotSurface2DX.XAxis1.TickTextNextToAxis = true;
            _plotSurface2DX.XAxis1.FlipTicksLabel = true;
            _plotSurface2DX.XAxis1.LabelOffset = 110;
            _plotSurface2DX.XAxis1.LabelOffsetAbsolute = true;
            _plotSurface2DX.XAxis1.LabelFont = AxisFont;
            _plotSurface2DX.XAxis1.TickTextFont = TickFont;

            //Y axis
            _plotSurface2DX.YAxis1.Label = "Value";
            _plotSurface2DX.YAxis1.NumberFormat = "{0:####0.0}";
            _plotSurface2DX.YAxis1.LabelFont = AxisFont;
            _plotSurface2DX.YAxis1.TickTextFont = TickFont;

            //Add legend:
            npLegend.AttachTo(NPlot.PlotSurface2D.XAxisPosition.Top,
                     NPlot.PlotSurface2D.YAxisPosition.Right);
            npLegend.VerticalEdgePlacement = NPlot.Legend.Placement.Inside;
            npLegend.HorizontalEdgePlacement = NPlot.Legend.Placement.Outside;
            npLegend.BorderStyle = NPlot.LegendBase.BorderType.Line;
            _plotSurface2DX.Legend = npLegend;

            //Update PlotSurface:
            _plotSurface2DX.Refresh();

            //Save PlotSurface to MemoryStream, stream output as GIF file:
            //Response.Buffer = true;
            //Response.ContentType = "image/gif";

            //MemoryStream memStream = new MemoryStream();

            //_plotSurface2D1.Bitmap.Save(memStream, System.Drawing.Imaging.ImageFormat.Gif);
            //memStream.WriteTo(Response.OutputStream);
            //Response.End();

        }
    }
}
